home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i031: Mail user's shell version 6.4, Part09/19
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Dan Heller <island!argv@sun.com>
- Posting-number: Volume 18, Issue 31
- Archive-name: mush6.4/part09
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 19)."
- # Contents: bind.c hdrs.c
- # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:15 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'bind.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bind.c'\"
- else
- echo shar: Extracting \"'bind.c'\" \(20444 characters\)
- sed "s/^X//" >'bind.c' <<'END_OF_FILE'
- X/* bind.c */
- X
- X#include "bindings.h"
- X#include "mush.h"
- X
- Xextern char *c_macro();
- Xstatic un_bind();
- X
- Xstruct cmd_map *cmd_map, *line_map, *bang_map;
- X
- X/*
- X * Bindings are added here in REVERSE of the order that
- X * they will be displayed! Display order is based on a
- X * guess about the frequency of use and (to a lesser
- X * extent) how hard they are to remember.
- X *
- X * The user's own new bindings, if any, will be displayed
- X * before any of these default bindings.
- X */
- Xinit_bindings()
- X{
- X#ifdef CURSES
- X /* Help gets displayed last */
- X add_bind("?", C_HELP, NULL, &cmd_map);
- X add_bind("V", C_VERSION, NULL, &cmd_map);
- X
- X /* Miscellaneous shell commands */
- X add_bind("%", C_CHDIR, NULL, &cmd_map);
- X add_bind("|", C_PRINT_MSG, NULL, &cmd_map);
- X add_bind("!", C_SHELL_ESC, NULL, &cmd_map);
- X add_bind(":", C_CURSES_ESC, NULL, &cmd_map);
- X
- X /* Mush customization commands */
- X /* NOTE: No default C_MACRO bindings */
- X add_bind(")", C_SAVEOPTS, NULL, &cmd_map);
- X add_bind("(", C_SOURCE, NULL, &cmd_map);
- X add_bind("&!", C_MAP_BANG, NULL, &cmd_map);
- X add_bind("&:", C_MAP, NULL, &cmd_map);
- X add_bind("&&", C_BIND_MACRO, NULL, &cmd_map);
- X add_bind("v", C_VAR_SET, NULL, &cmd_map);
- X add_bind("i", C_IGNORE, NULL, &cmd_map);
- X add_bind("h", C_OWN_HDR, NULL, &cmd_map);
- X add_bind("B", C_UNBIND, NULL, &cmd_map);
- X add_bind("b", C_BIND, NULL, &cmd_map);
- X add_bind("a", C_ALIAS, NULL, &cmd_map);
- X
- X /* Display modification commands */
- X add_bind("\022", C_REVERSE, NULL, &cmd_map); /* ^R */
- X add_bind("\014", C_REDRAW, NULL, &cmd_map); /* ^L */
- X add_bind("Z", C_PREV_SCREEN, NULL, &cmd_map);
- X add_bind("z", C_NEXT_SCREEN, NULL, &cmd_map);
- X
- X /* Searching and sorting commands */
- X add_bind("\016", C_CONT_SEARCH, NULL, &cmd_map); /* ^N */
- X add_bind("\037", C_PREV_SEARCH, NULL, &cmd_map); /* ^/ */
- X add_bind("/", C_NEXT_SEARCH, NULL, &cmd_map);
- X add_bind("O", C_REV_SORT, NULL, &cmd_map);
- X add_bind("o", C_SORT, NULL, &cmd_map);
- X
- X /* Ways to get out */
- X add_bind("X", C_EXIT_HARD, NULL, &cmd_map);
- X add_bind("x", C_EXIT, NULL, &cmd_map);
- X add_bind("Q", C_QUIT_HARD, NULL, &cmd_map);
- X add_bind("q", C_QUIT, NULL, &cmd_map);
- X
- X /* Folder modification commands */
- X add_bind("\025", C_UPDATE, NULL, &cmd_map); /* ^U */
- X add_bind("\020", C_PRESERVE, NULL, &cmd_map); /* ^P */
- X add_bind("W", C_WRITE_LIST, NULL, &cmd_map);
- X add_bind("w", C_WRITE_MSG, NULL, &cmd_map);
- X add_bind("U", C_UNDEL_LIST, NULL, &cmd_map);
- X add_bind("u", C_UNDEL_MSG, NULL, &cmd_map);
- X add_bind("S", C_SAVE_LIST, NULL, &cmd_map);
- X add_bind("s", C_SAVE_MSG, NULL, &cmd_map);
- X add_bind("f", C_FOLDER, NULL, &cmd_map);
- X add_bind("D", C_DELETE_LIST, NULL, &cmd_map);
- X add_bind("d", C_DELETE_MSG, NULL, &cmd_map);
- X add_bind("C", C_COPY_LIST, NULL, &cmd_map);
- X add_bind("c", C_COPY_MSG, NULL, &cmd_map);
- X
- X /* Cursor movement and message selection */
- X add_bind("g", C_GOTO_MSG, NULL, &cmd_map);
- X add_bind("}", C_BOTTOM_PAGE, NULL, &cmd_map);
- X add_bind("{", C_TOP_PAGE, NULL, &cmd_map);
- X add_bind("$", C_LAST_MSG, NULL, &cmd_map);
- X add_bind("^", C_FIRST_MSG, NULL, &cmd_map);
- X add_bind("\013",C_PREV_MSG, NULL, &cmd_map); /* ^K */
- X add_bind("\012", C_NEXT_MSG, NULL, &cmd_map); /* ^J */
- X add_bind("-",C_PREV_MSG, NULL, &cmd_map);
- X add_bind("+",C_NEXT_MSG, NULL, &cmd_map);
- X add_bind("K", C_PREV_MSG, NULL, &cmd_map);
- X add_bind("k", C_PREV_MSG, NULL, &cmd_map);
- X add_bind("J", C_NEXT_MSG, NULL, &cmd_map);
- X add_bind("j", C_NEXT_MSG, NULL, &cmd_map);
- X
- X /* Mail-sending commands */
- X add_bind("R", C_REPLY_ALL, NULL, &cmd_map);
- X add_bind("r", C_REPLY_SENDER, NULL, &cmd_map);
- X add_bind("M", C_MAIL_FLAGS, NULL, &cmd_map);
- X add_bind("m", C_MAIL, NULL, &cmd_map);
- X
- X /* Mail-reading commands */
- X add_bind(".", C_DISPLAY_MSG, NULL, &cmd_map);
- X add_bind("T", C_TOP_MSG, NULL, &cmd_map);
- X add_bind("t", C_DISPLAY_MSG, NULL, &cmd_map);
- X add_bind("p", C_DISPLAY_MSG, NULL, &cmd_map);
- X add_bind("n", C_DISPLAY_NEXT, NULL, &cmd_map);
- X
- X#endif /* CURSES */
- X}
- X
- X/* Bindable function names.
- X * Most of these can't be used if CURSES is not defined,
- X * but help and lookups get confused if they aren't all here.
- X */
- Xstruct cmd_map map_func_names[] = {
- X /* These MUST be in numerical order; see bindings.h */
- X { C_NULL, "no-op", NULL, NULL_MAP },
- X { C_GOTO_MSG, "goto-msg", NULL, NULL_MAP },
- X { C_WRITE_LIST, "write-list", NULL, NULL_MAP },
- X { C_WRITE_MSG, "write", NULL, NULL_MAP },
- X { C_SAVE_LIST, "save-list", NULL, NULL_MAP },
- X { C_SAVE_MSG, "save", NULL, NULL_MAP },
- X { C_COPY_LIST, "copy-list", NULL, NULL_MAP },
- X { C_COPY_MSG, "copy", NULL, NULL_MAP },
- X { C_DELETE_LIST, "delete-list", NULL, NULL_MAP },
- X { C_DELETE_MSG, "delete", NULL, NULL_MAP },
- X { C_UNDEL_LIST, "undelete-list", NULL, NULL_MAP },
- X { C_UNDEL_MSG, "undelete", NULL, NULL_MAP },
- X { C_REDRAW, "redraw", NULL, NULL_MAP },
- X { C_REVERSE, "reverse-video", NULL, NULL_MAP },
- X { C_NEXT_MSG, "next-msg", NULL, NULL_MAP },
- X { C_PREV_MSG, "back-msg", NULL, NULL_MAP },
- X { C_FIRST_MSG, "first-msg", NULL, NULL_MAP },
- X { C_LAST_MSG, "last-msg", NULL, NULL_MAP },
- X { C_TOP_PAGE, "top-page", NULL, NULL_MAP },
- X { C_BOTTOM_PAGE, "bottom-page", NULL, NULL_MAP },
- X { C_NEXT_SCREEN, "screen-next", NULL, NULL_MAP },
- X { C_PREV_SCREEN, "screen-back", NULL, NULL_MAP },
- X { C_SOURCE, "source", NULL, NULL_MAP },
- X { C_SAVEOPTS, "saveopts", NULL, NULL_MAP },
- X { C_NEXT_SEARCH, "search-next", NULL, NULL_MAP },
- X { C_PREV_SEARCH, "search-back", NULL, NULL_MAP },
- X { C_CONT_SEARCH, "search-again", NULL, NULL_MAP },
- X { C_PRESERVE, "preserve", NULL, NULL_MAP },
- X { C_REV_SORT, "sort-reverse", NULL, NULL_MAP },
- X { C_SORT, "sort", NULL, NULL_MAP },
- X { C_QUIT_HARD, "quit!", NULL, NULL_MAP },
- X { C_QUIT, "quit", NULL, NULL_MAP },
- X { C_EXIT_HARD, "exit!", NULL, NULL_MAP },
- X { C_EXIT, "exit", NULL, NULL_MAP },
- X { C_UPDATE, "update", NULL, NULL_MAP },
- X { C_FOLDER, "folder", NULL, NULL_MAP },
- X { C_SHELL_ESC, "shell-escape", NULL, NULL_MAP },
- X { C_CURSES_ESC, "line-mode", NULL, NULL_MAP },
- X { C_PRINT_MSG, "lpr", NULL, NULL_MAP },
- X { C_CHDIR, "chdir", NULL, NULL_MAP },
- X { C_VAR_SET, "variable", NULL, NULL_MAP },
- X { C_IGNORE, "ignore", NULL, NULL_MAP },
- X { C_ALIAS, "alias", NULL, NULL_MAP },
- X { C_OWN_HDR, "my-hdrs", NULL, NULL_MAP },
- X { C_VERSION, "version", NULL, NULL_MAP },
- X { C_MAIL_FLAGS, "mail-flags", NULL, NULL_MAP },
- X { C_MAIL, "mail", NULL, NULL_MAP },
- X { C_REPLY_ALL, "reply-all", NULL, NULL_MAP },
- X { C_REPLY_SENDER, "reply", NULL, NULL_MAP },
- X { C_DISPLAY_NEXT, "display-next", NULL, NULL_MAP },
- X { C_DISPLAY_MSG, "display", NULL, NULL_MAP },
- X { C_TOP_MSG, "top", NULL, NULL_MAP },
- X { C_BIND_MACRO, "bind-macro", NULL, NULL_MAP },
- X { C_BIND, "bind", NULL, NULL_MAP },
- X { C_UNBIND, "unbind", NULL, NULL_MAP },
- X { C_MAP_BANG, "map!", NULL, NULL_MAP },
- X { C_MAP, "map", NULL, NULL_MAP },
- X { C_MACRO, "macro", NULL, NULL_MAP },
- X /* C_HELP Must be the last one! */
- X { C_HELP, "help", NULL, NULL_MAP }
- X};
- X
- X#ifdef CURSES
- X
- X/*
- X * getcmd() is called from curses mode only. It waits for char input from
- X * the user via m_getchar() (which means that a macro could provide input)
- X * and then compares the chars input against the "bind"ings set up by the
- X * user (or the defaults). For example, 'j' could bind to "next msg" which
- X * is interpreted by the big switch statement in curses_command() (curses.c).
- X * getcmd() returns the int-value of the curses command the input is "bound"
- X * to. If the input is unrecognized, C_NULL is returned (curses_command()
- X * might require some cleanup, so this is valid, too).
- X *
- X * Since the input could originate from a macro rather than the terminal,
- X * check to see if this is the case and search for a '[' char which indicates
- X * that there is a curses command or other "long" command to be executed.
- X */
- Xgetcmd()
- X{
- X char buf[MAX_BIND_LEN * 3];
- X register int c, m, match;
- X register char *p = buf;
- X register struct cmd_map *list;
- X
- X bzero(buf, MAX_BIND_LEN);
- X active_cmd = NULL_MAP;
- X c = m_getchar();
- X /* If user did job control (^Z), then the interrupt flag will be
- X * set. Be sure it's unset before continuing.
- X */
- X turnoff(glob_flags, WAS_INTR);
- X if (isdigit(c)) {
- X buf[0] = c;
- X buf[1] = '\0';
- X Ungetstr(buf); /* So mac_flush can clear on error */
- X return C_GOTO_MSG;
- X }
- X for (;;) {
- X if (ison(glob_flags, IN_MACRO) && c == MAC_LONG_CMD)
- X return long_mac_cmd(c, TRUE);
- X else
- X *p++ = c;
- X m = 0;
- X for (list = cmd_map; list; list = list->m_next) {
- X if ((match = prefix(buf, list->m_str)) == MATCH) {
- X if (debug)
- X print("\"%s\" ",
- X ctrl_strcpy(buf,
- X map_func_names[list->m_cmd].m_str,
- X TRUE));
- X if (list->m_cmd == C_MACRO) {
- X curs_macro(list->x_str);
- X return getcmd();
- X }
- X active_cmd = list;
- X return (int)list->m_cmd;
- X } else if (match != NO_MATCH)
- X m++;
- X }
- X if (m == 0) {
- X if (debug) {
- X char tmp[sizeof buf];
- X print("No binding for \"%s\" found.",
- X ctrl_strcpy(tmp, buf, TRUE));
- X }
- X return C_NULL;
- X }
- X c = m_getchar();
- X }
- X}
- X
- X#endif /* CURSES */
- X
- X/*
- X * bind_it() is used to set or unset bind, map and map! settings.
- X * bind is used to accelerate curses commands by mapping key sequences
- X * to curses commands. map is used to accelerate command mode keysequences
- X * by simulating stdin. map! is the same, but used when in compose mode.
- X *
- X * bind_it() doesn't touch messages; return -1 for curses mode.
- X * return -2 to have curses command set CNTD_CMD to prevent screen refresh
- X * to allow user to read output in case of multiple lines.
- X *
- X * Since this routine deals with a lot of binding and unbinding of things
- X * like line-mode "map"s and is interactive (calls Getstr()), be very careful
- X * not to allow expansions during interaction.
- X */
- Xbind_it(len, argv)
- Xchar **argv;
- X{
- X char string[MAX_BIND_LEN], buf[256], *name = NULL;
- X char *rawstr; /* raw format of string (ptr to string if no argv avail) */
- X char ascii[MAX_BIND_LEN*2]; /* printable ascii version of string */
- X register int x;
- X SIGRET (*oldint)(), (*oldquit)();
- X struct cmd_map **map_list;
- X int unbind = (argv && **argv == 'u');
- X int map = 0, is_bind_macro = 0;
- X int ret = 0 - iscurses; /* return value */
- X
- X if (argv && !strcmp(name = *argv, "bind-macro"))
- X is_bind_macro++;
- X
- X if (map = (argv && (!strcmp(name, "map!") || !strcmp(name, "unmap!"))))
- X map_list = &bang_map;
- X else if (map = (argv && (!strcmp(name, "map") || !strcmp(name, "unmap"))))
- X map_list = &line_map;
- X else
- X map_list = &cmd_map;
- X
- X if (argv && *++argv && !strcmp(*argv, "-?"))
- X /* Subtract ret and iscurses to signal output */
- X return help(0, name, cmd_help) - ret - iscurses;
- X
- X if (iscurses)
- X on_intr();
- X
- X if (unbind) {
- X if (!*argv) {
- X print("%s what? ", name);
- X len = Getstr(buf, sizeof buf, 0);
- X if (len <= 0) {
- X if (iscurses)
- X off_intr();
- X return -1;
- X }
- X rawstr = m_xlate(buf);
- X } else
- X rawstr = m_xlate(*argv);
- X if (!un_bind(rawstr, map_list)) {
- X ctrl_strcpy(ascii, rawstr, TRUE);
- X print("\"%s\" isn't bound to a command.\n", ascii);
- X }
- X if (iscurses)
- X off_intr();
- X return ret;
- X }
- X if (argv && *argv) {
- X rawstr = m_xlate(*argv);
- X (void) ctrl_strcpy(ascii, rawstr, TRUE);
- X if (!*++argv) {
- X /*
- X * determine whether "argv" references a "map" or a "bind"
- X */
- X int binding = c_bind(rawstr, *map_list);
- X if (binding == C_MACRO) {
- X char *mapping = c_macro(NULL, rawstr, *map_list);
- X if (mapping) {
- X print("\"%s\" is mapped to ", ascii);
- X print_more("\"%s\".\n",
- X ctrl_strcpy(buf, mapping, FALSE));
- X } else
- X print("\"%s\" isn't mapped.\n", ascii);
- X } else if (binding)
- X print("\"%s\" is %s to \"%s\".\n", ascii,
- X map? "mapped" : "bound", map_func_names[binding].m_str);
- X else if (map)
- X print("\"%s\" isn't mapped.\n", ascii);
- X else
- X print("\"%s\" isn't bound to a command.\n", ascii);
- X if (iscurses)
- X off_intr();
- X return ret;
- X }
- X } else {
- X print("%s [<CR>=all, -?=help]: ", name);
- X len = Getstr(string, MAX_BIND_LEN-1, 0);
- X if (len == 0) {
- X int add_to_ret = iscurses;
- X#ifdef CURSES
- X if (iscurses)
- X move(LINES-1, 0), refresh();
- X#endif
- X if (map || is_bind_macro)
- X add_to_ret = !c_macro(name, NULL, *map_list);
- X else
- X add_to_ret = !c_bind(NULL, *map_list);
- X if (iscurses)
- X off_intr();
- X /* signal CTND_CMD if there was output */
- X return ret - add_to_ret;
- X }
- X if (len < 0) {
- X if (iscurses)
- X off_intr();
- X return ret;
- X }
- X rawstr = m_xlate(string);
- X (void) ctrl_strcpy(ascii, rawstr, TRUE);
- X }
- X /* if a binding was given on the command line */
- X if (argv && *argv && !map)
- X if (is_bind_macro)
- X (void) strcpy(buf, "macro");
- X else
- X (void) strcpy(buf, *argv++);
- X else {
- X /* at this point, "rawstr" and "ascii" should both be set */
- X int binding;
- X
- X if (!strcmp(ascii, "-?")) {
- X if (iscurses)
- X clr_bot_line();
- X ret -= help(0, name, cmd_help);
- X if (iscurses)
- X off_intr();
- X /* Subtract iscurses to signal CNTD_CMD */
- X return ret - iscurses;
- X }
- X
- X if (!map && !is_bind_macro) {
- X binding = c_bind(rawstr, *map_list);
- X
- X for (len = 0; len == 0; ) {
- X print("\"%s\" = <%s>: New binding [<CR> for list]: ",
- X ascii, (binding? map_func_names[binding].m_str : "unset"));
- X len = Getstr(buf, sizeof buf, 0);
- X if (iscurses)
- X clr_bot_line();
- X /* strip any trailing whitespace */
- X if (len > 0)
- X len = no_newln(buf) - buf;
- X if (len == 0) {
- X (void) do_pager(NULL, TRUE);
- X if (iscurses)
- X putchar('\n');
- X for (x = 1; x <= C_HELP; x++) {
- X if (!(x % 4))
- X if (do_pager("\n", FALSE) == EOF)
- X break;
- X (void) do_pager(sprintf(buf, "%-15.15s ",
- X map_func_names[x].m_str), FALSE);
- X }
- X (void) do_pager("\n", FALSE);
- X (void) do_pager(NULL, FALSE);
- X ret -= iscurses;
- X }
- X }
- X } else /* map */
- X (void) strcpy(buf, "macro"), len = 5;
- X /* if list was printed, ret < -1 -- tells CNTD_CMD to be set and
- X * prevents screen from being refreshed (lets user read output
- X */
- X if (len == -1) {
- X if (iscurses)
- X off_intr();
- X return ret;
- X }
- X }
- X for (x = 1; x <= C_HELP; x++) {
- X if (prefix(buf, map_func_names[x].m_str) == MATCH) {
- X int add_to_ret;
- X if (debug)
- X print("\"%s\" will execute \"%s\".\n", ascii, buf);
- X if (map_func_names[x].m_cmd == C_MACRO) {
- X if (argv && *argv) {
- X (void) argv_to_string(buf, argv);
- X (void) m_xlate(buf); /* Convert buf to raw chars */
- X add_to_ret =
- X do_bind(rawstr, map_func_names[x].m_cmd, buf, map_list);
- X } else {
- X char exp[MAX_MACRO_LEN*2]; /* printable expansion */
- X char *mapping = c_macro(NULL, rawstr, *map_list);
- X
- X if (mapping)
- X (void) ctrl_strcpy(exp, mapping, TRUE);
- X print("\"%s\" = <%s>", ascii, mapping ? exp : "unset");
- X putchar('\n'), print("New macro: ");
- X ret -= iscurses; /* To signal screen messed up */
- X /* we are done with buf, so we can trash over it */
- X len = Getstr(buf, MAX_MACRO_LEN, 0);
- X if (len > 0) {
- X if (iscurses)
- X clr_bot_line();
- X (void) m_xlate(buf); /* Convert buf to raw chars */
- X add_to_ret =
- X do_bind(rawstr, C_MACRO, buf, map_list);
- X if (debug) {
- X (void) ctrl_strcpy(exp, buf, TRUE);
- X print("\"%s\" will execute \"%s\".\n", ascii, exp);
- X }
- X } else if (len < 0) {
- X if (iscurses)
- X off_intr();
- X return ret - add_to_ret;
- X } else
- X print("Can't bind to null macro"), putchar('\n');
- X }
- X } else /* not a macro */ {
- X (void) argv_to_string(buf, argv);
- X add_to_ret =
- X do_bind(rawstr, map_func_names[x].m_cmd, buf, map_list);
- X }
- X /* if do_bind had no errors, it returned -1. If we already
- X * messed up the screen, then ret is less than -1. return the
- X * lesser of the two to make sure that CNTD_CMD gets set right
- X */
- X if (iscurses)
- X off_intr();
- X return min(add_to_ret, ret);
- X }
- X }
- X print("\"%s\": Unknown function.\n", buf);
- X if (iscurses)
- X off_intr();
- X return ret;
- X}
- X
- X/*
- X * print current key to command bindings if "str" is NULL.
- X * else return the integer "m_cmd" which the str is bound to.
- X */
- Xc_bind(str, opts)
- Xregister char *str;
- Xregister struct cmd_map *opts;
- X{
- X register int incurses = iscurses;
- X
- X if (!str) {
- X if (!opts) {
- X print("No command bindings.\n");
- X return C_ERROR;
- X }
- X if (incurses)
- X clr_bot_line(), iscurses = FALSE;
- X (void) do_pager(NULL, TRUE);
- X (void) do_pager("Current key to command bindings:\n", FALSE);
- X (void) do_pager("\n", FALSE);
- X }
- X
- X for (; opts; opts = opts->m_next) {
- X char buf[BUFSIZ], buf2[MAX_BIND_LEN], exp[MAX_MACRO_LEN*2], *xp;
- X if (!str) {
- X (void) ctrl_strcpy(buf2, opts->m_str, FALSE);
- X if ((xp = opts->x_str) && opts->m_cmd == C_MACRO)
- X xp = ctrl_strcpy(exp, opts->x_str, TRUE);
- X if (do_pager(sprintf(buf, "%s\t%-15.15s %s\n",
- X buf2, map_func_names[opts->m_cmd].m_str,
- X xp? xp : ""),
- X FALSE) == EOF)
- X break;
- X } else
- X if (strcmp(str, opts->m_str))
- X continue;
- X else
- X return opts->m_cmd;
- X }
- X
- X iscurses = incurses;
- X if (!str)
- X (void) do_pager(NULL, FALSE);
- X return C_NULL;
- X}
- X
- X/*
- X * Doesn't touch messages, but changes macros: return -1.
- X * Error output causes return < -1.
- X * args is currently the execute string of a macro mapping, but may be
- X * used in the future as an argument string for any curses command.
- X */
- Xdo_bind(str, func, args, map_list)
- Xregister char *str, *args;
- Xstruct cmd_map **map_list;
- Xlong func;
- X{
- X register int ret = -1;
- X register struct cmd_map *list;
- X int match;
- X
- X if (func == C_MACRO && !check_mac_bindings(args))
- X --ret;
- X (void) un_bind(str, map_list);
- X for (list = *map_list; list; list = list->m_next)
- X if ((match = prefix(str, list->m_str)) != NO_MATCH) {
- X ret--;
- X switch (match) {
- X case MATCH:
- X puts("Something impossible just happened.");
- X when A_PREFIX_B:
- X wprint("Warning: \"%s\" prefixes \"%s\" (%s)\n", str,
- X list->m_str, map_func_names[list->m_cmd].m_str);
- X when B_PREFIX_A:
- X wprint("Warning: \"%s\" (%s) prefixes: \"%s\"\n",
- X list->m_str, map_func_names[list->m_cmd].m_str, str);
- X }
- X }
- X add_bind(str, func, args, map_list);
- X /* errors decrement ret. If ret returns less than -1, CNTD_CMD is set
- X * and no redrawing is done so user can see the warning signs
- X */
- X return ret;
- X}
- X
- X/*
- X * add a binding to a list. This may include "map"s or other mappings since
- X * the map_list argument can control that. The "func" is an int defined in
- X * bindings.h ... the "str" passed is the string the user would have to type
- X * to get the macro/map/binding expanded. This must in in raw format: no
- X * \n's to mean \015. Convert first using m_xlate().
- X */
- Xadd_bind(str, func, args, map_list)
- Xregister char *str, *args;
- Xstruct cmd_map **map_list;
- Xlong func;
- X{
- X register struct cmd_map *tmp;
- X struct cmd_map *calloc();
- X
- X if (!str || !*str)
- X return;
- X
- X /* now make a new option struct and set fields */
- X if (!(tmp = calloc((unsigned)1, sizeof(struct cmd_map)))) {
- X error("calloc");
- X return;
- X }
- X tmp->m_next = *map_list;
- X *map_list = tmp;
- X
- X tmp->m_str = savestr(str);
- X tmp->m_cmd = func; /* strdup handles the NULL case */
- X if (args && *args)
- X tmp->x_str = savestr(args);
- X else
- X tmp->x_str = NULL;
- X}
- X
- Xstatic
- Xun_bind(p, map_list)
- Xregister char *p;
- Xstruct cmd_map **map_list;
- X{
- X register struct cmd_map *list = *map_list, *tmp;
- X
- X if (!list || !*list->m_str || !p || !*p)
- X return 0;
- X
- X if (!strcmp(p, (*map_list)->m_str)) {
- X *map_list = (*map_list)->m_next;
- X xfree (list->m_str);
- X if (list->x_str)
- X xfree (list->x_str);
- X xfree((char *)list);
- X return 1;
- X }
- X for ( ; list->m_next; list = list->m_next)
- X if (!strcmp(p, list->m_next->m_str)) {
- X tmp = list->m_next;
- X list->m_next = list->m_next->m_next;
- X xfree (tmp->m_str);
- X if (tmp->x_str)
- X xfree (tmp->x_str);
- X xfree ((char *)tmp);
- X return 1;
- X }
- X return 0;
- X}
- X
- Xprefix(a, b)
- Xregister char *a, *b;
- X{
- X if (!a || !b)
- X return NO_MATCH;
- X
- X while (*a && *b && *a == *b)
- X a++, b++;
- X if (!*a && !*b)
- X return MATCH;
- X if (!*a && *b)
- X return A_PREFIX_B;
- X if (*a && !*b)
- X return B_PREFIX_A;
- X return NO_MATCH;
- X}
- END_OF_FILE
- if test 20444 -ne `wc -c <'bind.c'`; then
- echo shar: \"'bind.c'\" unpacked with wrong size!
- fi
- # end of 'bind.c'
- fi
- if test -f 'hdrs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hdrs.c'\"
- else
- echo shar: Extracting \"'hdrs.c'\" \(18781 characters\)
- sed "s/^X//" >'hdrs.c' <<'END_OF_FILE'
- X/* hdrs.c (c) copyright 1986 (Dan Heller) */
- X
- X/*
- X * Routines that deal with message headers inside messages
- X * msg_get(n, from, count) -- get the From_ line in msg n into "from".
- X * header_field(n, str) -- get the header named "str" from msg n.
- X * do_hdrs(argc, argv, list) -- diplay message headers.
- X * specl_hdrs(argv, list) -- display msgs that share common attributes.
- X * compose_hdr(cnt) -- compose a message header from msg n.
- X * reply_to(n, all, buf) -- construct a header based on the To: header of n.
- X * subject_to(n, buf) -- get the subject for replying to msg n.
- X * cc_to(n, buf) -- construct a Cc header based on the Cc of message n.
- X */
- X#include "mush.h"
- X
- X/*
- X * Get a message from the current folder by its offset.
- X * Copy the From_ line to the second argument if the third arg > 0,
- X * and return the second argument, or NULL on an error.
- X */
- Xchar *
- Xmsg_get(n, from, count)
- Xint n, count;
- Xchar *from;
- X{
- X if (fseek(tmpf, msg[n].m_offset, L_SET) == -1) {
- X error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
- X turnon(glob_flags, READ_ONLY);
- X return NULL;
- X }
- X if (count)
- X#ifndef MSG_SEPARATOR
- X return fgets(from, count, tmpf);
- X#else
- X *from = '\0';
- X#endif
- X return from;
- X}
- X
- X/*
- X * get which message via the offset and search for the headers which
- X * match the string "str". there may be more than one of a field (like Cc:)
- X * so get them all and "cat" them together into the static buffer
- X * "buf" and return its address.
- X */
- Xchar *
- Xheader_field(n, str)
- Xchar *str;
- X{
- X static char buf[HDRSIZ];
- X char tmp[HDRSIZ];
- X register char *p, *p2, *b = buf;
- X int contd_hdr; /* true if next line is a continuation of the hdr we want */
- X
- X if (!msg_get(n, tmp, sizeof tmp))
- X return NULL;
- X *b = 0;
- X while((p = fgets(tmp, sizeof(tmp), tmpf)) && *p != '\n') {
- X if (*p != ' ' && *p != '\t') {
- X contd_hdr = 0;
- X /* strcmp ignoring case */
- X for(p2 = str; *p && *p2 && *p2 == lower(*p); ++p, ++p2);
- X /* MATCH is true if p2 is at the end of str and *p is ':' */
- X if (*p2 || *p++ != ':')
- X continue;
- X else
- X contd_hdr = 1;
- X } else if (!contd_hdr)
- X continue;
- X skipspaces(0);
- X p2 = no_newln(p);
- X *++p2 = ',', *++p2 = ' ', *++p2 = 0;
- X if (strlen(p) + (b-buf) < sizeof (buf))
- X b += Strcpy(b, p);
- X }
- X if (b > buf) /* now get rid of the trailing ", " */
- X *--b = 0, *--b = 0;
- X return (*buf)? buf: NULL;
- X}
- X
- Xdo_hdrs(argc, argv, list)
- Xregister char **argv, list[];
- X{
- X register int pageful = 0;
- X SIGRET (*oldint)(), (*oldquit)();
- X int show_deleted;
- X static int cnt;
- X register char *p;
- X char first_char = (argc) ? **argv: 'h';
- X
- X if (argc > 1 && !strcmp(argv[1], "-?"))
- X return help(0, "headers", cmd_help);
- X
- X if (!msg_cnt) {
- X if (ison(glob_flags, DO_PIPE))
- X return 0;
- X#ifdef CURSES
- X if (iscurses)
- X clear();
- X#endif /* CURSES */
- X#ifdef SUNTOOL
- X if (istool)
- X mail_status(0);
- X#endif /* SUNTOOL */
- X return 0;
- X }
- X if (first_char == ':' || (argc > 1 && argv[1][0] == ':')) {
- X if (first_char != ':')
- X argv++;
- X return specl_hdrs(argv, list);
- X }
- X
- X on_intr();
- X
- X if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
- X first_char == 'z' && !argv[1])
- X if (msg_cnt > screen)
- X cnt = min(msg_cnt - screen, n_array[0] + screen);
- X else
- X cnt = 0;
- X else if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
- X cnt = max((cnt - 2*screen), 0);
- X else if (argc && *++argv &&
- X (isdigit(**argv) || **argv == '^' || **argv == '$' || **argv == '.')
- X || ison(glob_flags, IS_PIPE)) {
- X /* if we're coming from a pipe, start display at the first msg bit
- X * set in the msg_list
- X */
- X int fnd;
- X if (ison(glob_flags, IS_PIPE)) {
- X if (isoff(glob_flags, DO_PIPE))
- X for (fnd = 0; fnd < msg_cnt; fnd++)
- X if (msg_bit(list, fnd))
- X wprint("%s\n", compose_hdr(fnd));
- X off_intr();
- X return 0;
- X }
- X /* if a number was given, use it */
- X if (!(fnd = chk_msg(*argv))) {
- X off_intr();
- X return -1;
- X }
- X for (cnt = fnd - 1; cnt > 0 && cnt + screen > msg_cnt; cnt--)
- X ;
- X } else if (current_msg < n_array[0] || current_msg > n_array[screen-1])
- X cnt = current_msg; /* adjust if reads have passed screen bounds */
- X else if (cnt >= msg_cnt || !argc || !*argv)
- X cnt = max((cnt - screen), 0); /* adjust window to maintain position */
- X
- X show_deleted = !!do_set(set_options, "show_deleted");
- X
- X /* Make sure we have at least $screen headers to print */
- X if (cnt > 0 && !iscurses && !show_deleted && first_char != 'h') {
- X int tmp = cnt;
- X /* first count how many messages we can print without adjusting */
- X for (pageful = 0; pageful < screen && cnt < msg_cnt; cnt++)
- X if (isoff(msg[cnt].m_flags, DELETE))
- X pageful++;
- X /* if we can't print a pagefull of hdrs, back up till we can */
- X for (cnt = tmp; pageful < screen && cnt; --cnt)
- X if (isoff(msg[cnt].m_flags, DELETE))
- X pageful++;
- X pageful = 0; /* Used later as an index, so reset */
- X }
- X
- X for (;pageful<screen && cnt<msg_cnt && isoff(glob_flags, WAS_INTR); cnt++) {
- X if (!iscurses && !show_deleted && first_char == 'h'
- X && ison(msg[cnt].m_flags, DELETE))
- X continue;
- X n_array[pageful++] = cnt;
- X /* this message was displayed -- set the bit */
- X if (list)
- X set_msg_bit(list, cnt);
- X /* if do_pipe, don't output anything */
- X if (ison(glob_flags, DO_PIPE))
- X continue;
- X p = compose_hdr(cnt);
- X if (!istool && (!iscurses || ison(glob_flags, IS_GETTING)))
- X puts(p);
- X#ifdef SUNTOOL
- X else if (istool) {
- X if (cnt == current_msg) /* embolden or reverse-video */
- X highlight(hdr_win, 0,pageful*l_height(DEFAULT), DEFAULT,p);
- X else
- X pw_text(hdr_win, 0, pageful * l_height(DEFAULT), PIX_SRC,
- X fonts[DEFAULT], p);
- X Clrtoeol(hdr_win, strlen(p)*l_width(DEFAULT),
- X pageful*l_height(DEFAULT), DEFAULT);
- X }
- X#endif /* SUNTOOL */
- X#ifdef CURSES
- X else if (iscurses) {
- X move(pageful, 0);
- X printw("%-.*s", COLS-2, p), clrtoeol();
- X }
- X#endif /* CURSES */
- X }
- X /* just in case a signal stopped us */
- X off_intr();
- X pageful++;
- X#ifdef CURSES
- X if (iscurses && pageful < screen)
- X move(pageful, 0), clrtobot();
- X#endif /* CURSES */
- X if (cnt == msg_cnt) {
- X while (pageful <= screen) {
- X n_array[pageful-1] = msg_cnt+1; /* assign out-of-range values */
- X#ifdef SUNTOOL
- X if (istool)
- X Clrtoeol(hdr_win, 0, pageful * l_height(DEFAULT), DEFAULT);
- X#endif /* SUNTOOL */
- X ++pageful;
- X }
- X }
- X#ifdef SUNTOOL
- X if (istool) {
- X if (msg_cnt > screen) {
- X panel_set(next_scr, PANEL_SHOW_ITEM, TRUE, 0);
- X panel_set(prev_scr, PANEL_SHOW_ITEM, TRUE, 0);
- X }
- X mail_status(0);
- X }
- X#endif /* SUNTOOL */
- X return 0;
- X}
- X
- X#define NEW 1
- X#define ALL 2
- X
- Xspecl_hdrs(argv, list)
- Xchar **argv, list[];
- X{
- X u_long special = 0;
- X int n = 0;
- X
- X while (argv[0][++n])
- X switch(argv[0][n]) {
- X case 'a': special = ALL;
- X when 'n': special = NEW;
- X when 'u': special = UNREAD;
- X when 'o': special = OLD;
- X when 'd': special = DELETE;
- X when 'r': special = REPLIED;
- X when 's': special = SAVED;
- X when 'p': special = PRESERVE;
- X otherwise: print("choose from n,u,o,d,r,s,p or a"); return -1;
- X }
- X if (debug)
- X (void) check_flags(special);
- X
- X for (n = 0; n < msg_cnt; n++) {
- X /*
- X * First, see if we're looking for NEW messages.
- X * If so, then check to see if the msg is unread and not old.
- X * If special > ALL, then special has a mask of bits describing
- X * the state of the message.
- X */
- X if (ison(glob_flags, IS_PIPE)&& !msg_bit(list, n))
- X continue;
- X if (special == ALL || special == NEW &&
- X (ison(msg[n].m_flags, UNREAD) && isoff(msg[n].m_flags, OLD))) {
- X if (isoff(glob_flags, DO_PIPE))
- X print("%s\n", compose_hdr(n));
- X if (list)
- X set_msg_bit(list, n);
- X#ifndef M_XENIX
- X /*
- X * XENIX compiler can't handle "special" in ison() macro.
- X * It only works if the second argument is a constant!
- X */
- X } else if (special > ALL && ison(msg[n].m_flags, special)) {
- X if (isoff(glob_flags, DO_PIPE))
- X print("%s\n", compose_hdr(n));
- X if (list)
- X set_msg_bit(list, n);
- X#endif /* M_XENIX */
- X } else {
- X if (list)
- X unset_msg_bit(list, n);
- X if (debug) {
- X printf("msg[%d].m_flags: %d", n, msg[n].m_flags);
- X (void) check_flags(msg[n].m_flags);
- X }
- X }
- X }
- X return 0;
- X}
- X
- X#define Strncpy(buf,p) (void)(strncpy(buf,p,sizeof(buf)),buf[sizeof(buf)-1]=0)
- X
- X/*
- X * compose a header from the information about a message (from, to, date,
- X * subject, etc..). The header for message number "cnt" is built and is
- X * returned in the static buffer "buf". There will be *at least* 9 chars
- X * in the buffer which will be something like: " 123 >N " The breakdown
- X * is as follows: 4 chars for the message number, 1 space, 1 char for '>'
- X * (if current message) and two spaces for message status (new, unread, etc)
- X * followed by 1 terminating space.
- X * Read other comments in the routine for more info.
- X */
- Xchar *
- Xcompose_hdr(cnt)
- X{
- X static char buf[256];
- X register char *p, *p2, *b;
- X int len, do_pad = FALSE, val, pad, got_dot, isauthor = 0, n;
- X char from[HDRSIZ], subject[256], date[64], lines[16];
- X char to[256], addr[256], name[256], status[4];
- X char Day[3], Mon[4], Tm[8], Yr[5], Wkday[4], *date_p;
- X
- X /* status of the message */
- X if (ison(msg[cnt].m_flags, DELETE))
- X status[0] = '*';
- X else if (ison(msg[cnt].m_flags, PRESERVE))
- X status[0] = 'P';
- X else if (ison(msg[cnt].m_flags, SAVED))
- X status[0] = 'S';
- X else if (ison(msg[cnt].m_flags, OLD) && ison(msg[cnt].m_flags, UNREAD))
- X status[0] = 'U';
- X else if (isoff(msg[cnt].m_flags, UNREAD))
- X status[0] = ' ';
- X else
- X status[0] = 'N';
- X
- X if (ison(msg[cnt].m_flags, REPLIED))
- X status[1] = 'r';
- X else
- X status[1] = ' ';
- X
- X to[0] = from[0] = subject[0] = date[0] = lines[0] = addr[0] =
- X name[0] = Day[0] = Mon[0] = Tm[0] = Yr[0] = Wkday[0] = 0;
- X
- X /* who's the message to */
- X if ((p = header_field(cnt, "resent-to")) ||
- X (p = header_field(cnt, "to")) ||
- X (p = header_field(cnt, "apparently-to")))
- X Strncpy(to, p);
- X
- X /* who's the message from */
- X if ((p = header_field(cnt, "from")) && strcpy(from, p)
- X || (p = reply_to(cnt, 0, from))) {
- X /* NOTE: this fails if the sender has '<' or '!' in
- X * the RFC822 comment fields -- leading "comment"
- X * or trailing (comment) -- but that isn't critical
- X */
- X if ((p2 = rindex(p, '!')) || (p2 = index(p, '<')))
- X p = p2 + 1;
- X } else
- X p = strcpy(from, "unknown"); /* just in case */
- X /* If the From field contains the user's login name, then the message is
- X * from the user -- attempt to give more useful information by telling
- X * to whom the message was sent. This is not possible if the "to" header
- X * failed to get info (which is probably impossible).
- X */
- X if (!strncmp(p, login, strlen(login))) {
- X isauthor = TRUE;
- X (void) get_name_n_addr(to, name+4, addr+4);
- X if (addr[4])
- X (void) strncpy(addr, "TO: ", 4);
- X if (name[4]) { /* check to see if a name got added */
- X (void) strncpy(name, "TO: ", 4);
- X Strncpy(from, name);
- X } else
- X Strncpy(from, addr);
- X } else
- X (void) get_name_n_addr(from, name, addr);
- X
- X if (ison(glob_flags, DATE_RECV))
- X date_p = msg[cnt].m_date_recv;
- X else
- X date_p = msg[cnt].m_date_sent;
- X date_to_string(date_p, Yr, Mon, Day, Wkday, Tm, date);
- X
- X /* and the subject */
- X if (p = header_field(cnt, "subject"))
- X Strncpy(subject, p);
- X
- X /* now, construct a header out of a format string */
- X if (!hdr_format)
- X hdr_format = DEF_HDR_FMT;
- X
- X (void) sprintf(buf, "%4.d ", cnt+1);
- X b = buf+5;
- X *b++ = ((cnt == current_msg && !iscurses)? '>': ' ');
- X *b++ = status[0], *b++ = status[1];
- X *b++ = ' ';
- X /* Count chars since beginning of buf. Initialize to 9 (strlen(buf) so far)
- X * This magic number is used in other places in msgs.c and mail.c
- X */
- X n = 9;
- X for (p = hdr_format; *p; p++)
- X if (*p == '\\')
- X switch (*++p) {
- X case 't':
- X while (n % 8)
- X n++, *b++ = ' ';
- X when 'n':
- X n = 1, *b++ = '\n';
- X otherwise: n++, *b++ = *p;
- X }
- X else if (*p == '%') {
- X char fmt[64];
- X
- X p2 = fmt;
- X /* first check for string padding: %5n, %.4a, %10.5f, %-.3l etc. */
- X do_pad = pad = val = got_dot = 0;
- X *p2++ = '%';
- X if (p[1] != '-')
- X *p2++ = '-';
- X else
- X ++p;
- X while (isdigit(*++p) || !got_dot && *p == '.') {
- X if (*p == '.')
- X got_dot = TRUE, val = pad, pad = 0;
- X else
- X pad = pad * 10 + *p - '0';
- X *p2++ = *p;
- X }
- X if (!got_dot && isdigit(p[-1])) {
- X *p2 = 0; /* assure null termination */
- X val = atoi(fmt+1);
- X if (val < 0)
- X val = -val;
- X p2 += strlen(sprintf(p2, ".%d", val));
- X }
- X pad = min(pad, val);
- X *p2++ = 's', *p2 = 0;
- X switch (*p) {
- X case 'f': p2 = from, do_pad = TRUE;
- X when 'a':
- X if (!*(p2 = addr))
- X p2 = from;
- X do_pad = TRUE;
- X when 'n':
- X if (!*(p2 = name))
- X p2 = from, do_pad = TRUE;
- X when '%': p2 = "%";
- X when 't': p2 = to;
- X when 's': p2 = subject;
- X when 'l': p2 = sprintf(lines, "%d", msg[cnt].m_lines);
- X when 'c': p2 = sprintf(lines, "%ld", msg[cnt].m_size);
- X when 'i': p2 = header_field(cnt, "message-id");
- X /* date formatting chars */
- X when 'd': p2 = date; /* the full date */
- X when 'T': p2 = Tm;
- X when 'M': p2 = Mon;
- X when 'Y': p2 = Yr;
- X when 'y': p2 = Yr+2;
- X when 'N': p2 = Day;
- X when 'D': case 'W': p2 = Wkday;
- X otherwise: continue; /* unknown formatting char */
- X }
- X if (do_pad && pad && strlen(p2) > pad) {
- X char *old_p2 = p2, *p3;
- X /* if addr is too long, move pointer forward till the
- X * "important" part is readable only for ! paths/addresses.
- X */
- X while (p3 = index(p2, '!')) {
- X int tmp = strlen(p3+1); /* xenix has compiler problems */
- X p2 = p3+1;
- X if (tmp + isauthor*4 < pad) {
- X if (isauthor && (p2 -= 4) < old_p2)
- X p2 = old_p2;
- X break;
- X }
- X }
- X if (isauthor && p2 > old_p2+4 && !p3 && strlen(p2) + 4 > pad)
- X p2 -= 4;
- X if (old_p2 != p2 && isauthor)
- X (void) strncpy(p2, "TO: ", 4); /* doesn't null terminate */
- X }
- X len = strlen(sprintf(b, fmt, p2));
- X n += len, b += len;
- X /* Get around a bug in 5.5 IBM RT which pads with NULs not ' ' */
- X while (n && !*(b-1))
- X b--, n--;
- X } else
- X n++, *b++ = *p;
- X for (*b-- = 0; isspace(*b) && *b != '\n'; --b)
- X *b = 0;
- X return buf;
- X}
- X
- X/*
- X * Using message "n", build a list of recipients that you would mail to if
- X * you were to reply to this message. If "all" is true, then it will take
- X * everyone from the To line in addition to the original sender.
- X * route_addresses() is called from mail.c, not from here. There are too many
- X * other uses for reply_to to always require reconstruction of return paths.
- X * Note that we do NOT deal with Cc paths here either.
- X * Check to make sure that we in fact return a legit address (i.e. not blanks
- X * or null). If such a case occurs, return login name. Always pad end w/blank.
- X */
- Xchar *
- Xreply_to(n, all, buf)
- Xchar buf[];
- X{
- X register char *p = NULL, *p2, *b = buf, *field;
- X char line[256], name[256], addr[256];
- X
- X if (field = do_set(set_options, "reply_to_hdr")) {
- X#ifndef MSG_SEPARATOR
- X if (!*field)
- X goto DoFrom; /* special case -- get the colon-less From line */
- X#endif /* MSG_SEPARATOR */
- X field = lcase_strcpy(line, field);
- X while (*field) {
- X if (p2 = any(field, " \t,:"))
- X *p2 = 0;
- X#ifndef MSG_SEPARATOR
- X if (!lcase_strncmp(field, "from_", -1))
- X goto DoFrom;
- X#endif /* MSG_SEPARATOR */
- X if ((p = header_field(n, field)) || !p2)
- X break;
- X else {
- X field = p2+1;
- X while (isspace(*field) || *field == ':' || *field == ',')
- X field++;
- X }
- X }
- X if (!p)
- X print("Warning: message contains no `reply_to_hdr' headers.\n");
- X }
- X if (p || (!p && ((p = header_field(n, field = "reply-to")) ||
- X (p = header_field(n, field = "return-path")) ||
- X (p = header_field(n, field = "from")))))
- X skipspaces(0);
- X else if (!p) {
- X#ifndef MSG_SEPARATOR
- XDoFrom:
- X field = "from_";
- X /* if all else fails, then get the first token in "From" line */
- X if (p2 = msg_get(n, line, sizeof line))
- X p = index(p2, ' ');
- X else
- X return "";
- X skipspaces(1);
- X if (p2 = index(p, ' '))
- X *p2 = 0;
- X (void) unscramble_addr(p, line); /* p is safely recopied to line */
- X p = line;
- X#else /* MSG_SEPARATOR */
- X wprint("Warning: unable to find who msg %d is from!\n", n+1);
- X#endif /* MSG_SEPARATOR */
- X }
- X get_name_n_addr(p, name, addr);
- X if (!name[0] && (!lcase_strncmp(field, "return-path", -1) ||
- X !lcase_strncmp(field, "from_", -1))) {
- X /*
- X * Get the name of the author of the message we're replying to from the
- X * From: header since that header contains the author's name. Only do
- X * this if the address was gotten from the return-path or from_ lines
- X * because this is the only way to guarantee that the return address
- X * matches the author's name. Reply-To: may not be the same person!
- X * Check Resent-From: first since that's presumably more recent.
- X */
- X if ((p = header_field(n, "resent-from")) ||
- X (p = header_field(n, "from")))
- X get_name_n_addr(p, name, NULL);
- X if (!name[0] && (p = header_field(n, "name")))
- X (void) strcpy(name, p);
- X if (name[0]) {
- X if ((p = any(name, "(<,\"")) && (*p == ',' || *p == '<'))
- X *b++ = '"';
- X b += Strcpy(b, name);
- X if (p && (*p == ',' || *p == '<'))
- X *b++ = '"';
- X *b++ = ' ', *b++ = '<';
- X }
- X b += Strcpy(b, addr);
- X if (name[0])
- X *b++ = '>', *b = 0;
- X } else
- X b += Strcpy(buf, p);
- X
- X /*
- X * if `all' is true, append everyone on the "To:" line.
- X * cc_to(), called separately, will catch the cc's
- X */
- X if (all &&
- X ((p = header_field(n, "resent-to")) || (p = header_field(n, "to")) ||
- X (p = header_field(n, "apparently-to"))) && *p) {
- X *b++ = ',', *b++ = ' ';
- X /* The assumption that HDRSIZ is correct is unwise, but I know it
- X * to be true for Mush. Be forewarned if you call this routine.
- X */
- X p[HDRSIZ - (b - buf) - 2] = '\0'; /* prevent overflow */
- X b += Strcpy(b, p);
- X }
- X /* Also append the Resent-From address if there is one. */
- X if (all && (p = header_field(n, "resent-from")) && *p) {
- X *b++ = ',', *b++ = ' ';
- X /* Another trick to prevent overflow. See warning above. */
- X (void) strncpy(b, p, HDRSIZ - (b - buf) - 2);
- X buf[HDRSIZ - 3] = 0;
- X }
- X fix_up_addr(buf);
- X take_me_off(buf);
- X for (p = buf; *p == ',' || isspace(*p); p++)
- X ;
- X if (!*p)
- X (void) strcpy(buf, login);
- X return buf;
- X}
- X
- Xchar *
- Xsubject_to(n, buf)
- Xregister char *buf;
- X{
- X register char *p;
- X buf[0] = 0; /* make sure it's already null terminated */
- X if (!(p = header_field(n, "subject")))
- X return NULL;
- X if (lcase_strncmp(p, "Re:", 3))
- X (void) strcpy(buf, "Re: ");
- X return strcat(buf, p);
- X}
- X
- Xchar *
- Xcc_to(n, buf)
- Xregister char *buf;
- X{
- X register char *p;
- X buf[0] = 0; /* make sure it's already null terminated */
- X if (!(p = header_field(n, "cc")))
- X return NULL;
- X fix_up_addr(p);
- X take_me_off(p);
- X return strcpy(buf, p);
- X}
- END_OF_FILE
- if test 18781 -ne `wc -c <'hdrs.c'`; then
- echo shar: \"'hdrs.c'\" unpacked with wrong size!
- fi
- # end of 'hdrs.c'
- fi
- echo shar: End of archive 9 \(of 19\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-